﻿#include "DxLib.h"
#include "Teigi.h"
#include "Key.h"
#include <Time.h>

#define BLOCKSIZE 23

typedef struct{
	int data;
	int color;
}MAPS;


//ステージの定義
MAPS Stage[21][12];

//フィールド	の定義
MAPS Field[21][12];


//ブロックの定義
int Block_List[7][4][4] = 
{{{0,1,0,0},				
{0,1,0,0},					
{0,1,0,0},					
{0,1,0,0}},				

{{0,0,0,0},		      
{0,1,1,0},				
{0,1,0,0},				  
{0,1,0,0}},			  

{{0,0,1,0}, 
{0,1,1,0}, 
{0,1,0,0}, 
{0,0,0,0}},

{{0,1,0,0}, 
{0,1,1,0}, 
{0,0,1,0}, 
{0,0,0,0}}, 

{{0,0,0,0}, 
{0,1,0,0}, 
{1,1,1,0}, 
{0,0,0,0}}, 

{{0,0,0,0}, 
{0,1,1,0}, 
{0,1,1,0}, 

{0,0,0,0}}, 
{{0,0,0,0}, 
{0,1,1,0}, 
{0,0,1,0}, 
{0,0,1,0}}}; 

int Block[4][4]={0};


//ブロックの色
int Block_Color[7]={ 
GetColor(0,255,255) ,
GetColor(0,0,255) ,
GetColor(255,0,0) , 
GetColor(0,255,0) , 
GetColor(255,0,255) ,
GetColor(255,255,0) ,
GetColor(255,128,0)};

int Block_in_Color[4][4]={0};


//現在のブロックタイプ
int Block_Type;


int y=0; //ブロックのステージ上のy座標
int x=4;//ブロックのステージ上のx座標

int color=0;

int F_GameOver=FALSE;//ゲームオーバーフラグ

void Init();			  //ゲームの初期化用関数
int CreateBlock();//ブロック作成用関数
void DrawGame();//表示用関数
void MoveBlock( int x2 ,int y2);	//ブロック移動用関数
int CheckOverlap(int x2 , int y2);  //ブロックの衝突判定用関数
void LockBlock();	//ブロックロック用関数
void ControlBlock();	 //ブロック操作用関数
int TurnBlock();	 //ブロック回転用関数
void CheckLines(); //ライン判定用関数



//ゲームを管理------------------------------------------------------------------------------------
int GameMgr(int *DS){

	static int time=0;

	//最初だけ初期化
	static int saisyo=FALSE;
	if(saisyo==FALSE){
		Init();
		saisyo=TRUE;
	}

	//キー入力に応じて動かす
	ControlBlock();


	//ブロックの落とすタイミングを計測(１秒で60増える)
	if(time<30){
		time++;
	}else{

		//重なりがあるかチェック
		if(CheckOverlap(x,y+1)==FALSE){
		
			
			//ブロックの移動
			MoveBlock(x,y+1);
		}else{

			//ブロックの固定と新しいブロックの生成
			LockBlock();
			CreateBlock();
			DrawGame();
		}

		//タイムを初期化
		time=0;
	}


	//表示
	DrawGame();

	*DS=NORMALMODE;
	return 0;
}



//ステージ、フィールドの初期化-----------------------------------------------------------------------
void Init(){

	int i,j;

	//ステージの初期化
	for(i=0;i<21;i++){
		for(j=0;j<12;j++){
			if((j==0) ||  (j==11) || (i==20)){

				Field[i][j].data=Stage[i][j].data=9;
				Field[i][j].color=Stage[i][j].color=GetColor(0,0,225);
			}

			else{
				Field[i][j].data=Stage[i][j].data=0;
			}
		}
	}
	CreateBlock();
	DrawGame();
}


//ゲームを表示-----------------------------------------------------------------------------
void  DrawGame()
{

	int black=GetColor(0,0,0);
	int white=GetColor(255,255,255);

	int i,j;

	DrawBox(0 , 0 , BLOCKSIZE*12 , BLOCKSIZE*22 , GetColor(0,0,0) , TRUE);

	for(i=0;i<21;i++){
		for(j=0;j<12;j++){

			switch(Field[i][j].data){

				case 9:

					DrawBox( BLOCKSIZE*j+1 ,BLOCKSIZE*i+1 , BLOCKSIZE*(j+1) , BLOCKSIZE*(i+1) ,Field[i][j].color,TRUE);
					break;

				case 0:
					DrawBox( BLOCKSIZE*j+1 ,BLOCKSIZE*i+1 , BLOCKSIZE*(j+1) , BLOCKSIZE*(i+1) ,white,TRUE);
					break;	 

				case 1:

					DrawBox( BLOCKSIZE*j+1 ,BLOCKSIZE*i+1 , BLOCKSIZE*(j+1) , BLOCKSIZE*(i+1), Field[i][j].color,TRUE);
					break;

			}
		}
	}

	//ゲームオーバーフラグが立っているなら表示
	if(F_GameOver==TRUE){
		DrawString(0,0,"GAMEOVER",white);
	}

}

//ブロックの生成--------------------------------------------------------------------------
int CreateBlock()
{

	int i , j;

	x=4;

	y=0;

	Block_Type=0;
	//乱数を生成して、その数を7でわってブロックを決める
	SRand((unsigned)time(NULL));
	Block_Type=GetRand(6);


	//ブロックを決定
	for(i=0;i<4;i++){
		for(j=0;j<4;j++){

			Block[i][j]=0;
			Block[i][j]=Block_List[Block_Type][i][j];
		}
	}

	//ブロックの色を代入
	for(i=0;i<4;i++){
		for(j=0;j<4;j++){
			Block_in_Color[i][j]=0;
			if(Block[i][j]==1){
				Block_in_Color[i][j]=Block_Color[Block_Type];
			}
		}
	}

	//フィールドにブロックを追加
	for(i=0;i<4;i++){
		for(j=0;j<4;j++){

			Field[i][j+4].data=Stage[i][j+4].data+Block[i][j];
			Field[i][j+4].color=Stage[i][j+4].color+Block_in_Color[i][j];

			//初期位置でブロックが重なればゲームオーバー
			if(Field[i][j+4].data>1){

				F_GameOver=TRUE;
				return 1;
			}
		}
	}
	return 0;
}

//ブロックを落とす-----------------------------------------------------------------------------
void MoveBlock(int x2 ,int y2)
{

	int i,j;

	//ブロックを消す
	for(i=0;i<4;i++){
		for(j=0;j<4;j++){

			Field[y+i][x+j].data-=Block[i][j];
			Field[y+i][x+j].color-=Block_in_Color[i][j];
		}
	}

	//座標更新
	x=x2;
	y=y2;

	//ブロックを表示
	for(i=0;i<4;i++){
		for(j=0;j<4;j++){

			Field[y+i][x+j].data+=Block[i][j];
			Field[y+i][x+j].color+=Block_in_Color[i][j];
		}
	}

	DrawGame();
}


//重なりがあるかチェック------------------------------------------------------------------
int CheckOverlap(int x2, int  y2)
{
	int i,j;

	for(i=0;i<4;i++){
		for(j=0;j<4;j++){

			//重なりがあったら
			if(Block[i][j]){
				if(Stage[y2+i][x2+j].data!=0){
					return 1;
				}
			}
		}
	}
	return 0;
}


//ブロックをステージに追加-----------------------------------------------------------------------------
void LockBlock()
{
	int i,j;

	for(i=0;i<21;i++){
		for(j=0;j<12;j++){

			Stage[i][j].data=Field[i][j].data;
			Stage[i][j].color=Field[i][j].color;
		}
	}

	CheckLines();

	for(i=0;i<21;i++){
		for(j=0;j<12;j++){

			Field[i][j].data=Stage[i][j].data;
			Field[i][j].color=Stage[i][j].color;
		}
	}


}



//ブロックをコントロール--------------------------------------------------------------------------------------
void ControlBlock()
{
	//←を押したら
	if(GetKey(KEY_INPUT_LEFT)==TRUE || GetKey(KEY_INPUT_LEFT)>=10){

		if(!CheckOverlap(x-1,y)){

			MoveBlock(x-1,y);
		}
	}


	//→を押したら
	if(GetKey(KEY_INPUT_RIGHT)==TRUE || GetKey(KEY_INPUT_RIGHT)>=10){

		if(!CheckOverlap(x+1,y)){

			MoveBlock(x+1,y);
		}
	}

	//↓を押したら
	if(GetKey(KEY_INPUT_DOWN)==TRUE || GetKey(KEY_INPUT_DOWN)>=10){

		if(!CheckOverlap(x,y+1)){

			MoveBlock(x,y+1);
		}
	}

	//スペースを押したら
	if(GetKey(KEY_INPUT_SPACE)==TRUE){

		TurnBlock();
	}
}


//ブロックの回転--------------------------------------------------------------------------------------------------
int  TurnBlock()
{
	int i , j ;

	int tmp[4][4]={0};
	int tmp_color[4][4]={0};
	
	//一時保存する
	for(i=0;i<4;i++){
		for(j=0;j<4;j++){
			tmp[i][j]=Block[i][j];
			tmp_color[i][j]=Block_in_Color[i][j];
		}
	}


	//ブロックを回転
	for(i=0;i<4;i++){
		for(j=0;j<4;j++){
		Block[i][j]=tmp[3-j][i];
		Block_in_Color[i][j]=tmp_color[3-j][i];
		}
	}


	//重なっていたら回転をもとに戻す
	if(CheckOverlap(x,y)){

		for(i=0;i<4;i++){
			for(j=0;j<4;j++){
				Block[i][j]=tmp[i][j];		
				Block_in_Color[i][j]=tmp_color[i][j];
		}
	}
			return 1;
	}

	//一旦ブロックを消して、回転したのを表示
	for(i=0;i<4;i++){
		for(j=0;j<4;j++){

			Field[y+i][x+j].data-=tmp[i][j];
			Field[y+i][x+j].color-=tmp_color[i][j];
			Field[y+i][x+j].data+=Block[i][j];
			Field[y+i][x+j].color+=Block_in_Color[i][j];

		}
	}

	DrawGame();
	return 0;
}


//ライン判定用関数----------------------------------------------------------------------------------------------------
void CheckLines()
{
	int i,j,k,w={0};
	int F_Comp;
	int Lines=0;

	while(1){

		for(i=0;i<20;i++){

			F_Comp=TRUE;

			for(j=1;j<11;j++){

				if(Stage[i][j].data==0){

					F_Comp=FALSE;
				}
			}

			if(F_Comp==TRUE) break;
		}

		if(F_Comp==FALSE) break;

		Lines++;

		while(w<800){
					 w++;
		}

		//列を消去
		for(j=1;j<11;j++){

			Stage[i][j].data=0;
			Stage[i][j].color=0;
		}

		//消えた列より上にあった列を下に落とす
		for(k=i;k>0;k--){
			for(j=1;j<11;j++){

				Stage[k][j].data=Stage[k-1][j].data;
				Stage[k][j].color=Stage[k-1][j].color;

			}
		}
	}
}